package com.ruoyi.system.services;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.config.GeoConfig;
import com.ruoyi.common.config.PersonPosition;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.EnclosureInfo;
import com.ruoyi.system.service.IEnclosureInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Slf4j
@Service("enclosureServices")
public class EnclosureServices {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IEnclosureInfoService enclosureInfoService;

    // 新增缓存键常量
    private static final String GEO_AREA_CACHE_KEY = "geo_area_id";

    /**
     * 查询第一个地图ID
     * @return
     */
    public Long getAreaId() {
        JSONArray jsonArray = getAllArea();
        JSONObject jsonObj = jsonArray!=null && !jsonArray.isEmpty() ? jsonArray.getJSONObject(0) : null;

        return jsonObj!=null && jsonObj.containsKey("id") ? jsonObj.getLong("id") : null;
    }

    /**
     * 获取所有地图信息 BY orgId=100
     *
     * @return
     */
    public JSONArray getAllArea() {
        /** 缓存中获取 areaID **/
        if (redisCache.hasKey(GEO_AREA_CACHE_KEY)) {
            JSONArray cachedArea = redisCache.getCacheObject(GEO_AREA_CACHE_KEY);
            log.info("从redis缓存中获取地图编号：{}", cachedArea);
            if (cachedArea!=null && !cachedArea.isEmpty()) {
                return cachedArea;
            }
        }

        /** 缓存中不存在，重新请求 **/
        JSONObject responseData = GeoConfig.sendGet(GeoConfig.areaDataUrl + GeoConfig.orgId + "?access_token=" + PersonPosition.getToken());
        JSONArray areaData = responseData.containsKey("data") ? responseData.getJSONArray("data") : null;
        log.info("绘制区域-作业计划模块-请求地图编号， 返回结果：{}", areaData);

        // 仅当获取到有效数据时才缓存
        if (areaData != null && !areaData.isEmpty()) {
            redisCache.setCacheObject(GEO_AREA_CACHE_KEY, areaData, 24, TimeUnit.HOURS);
        }
        return areaData;
    }


    /**
     * 作业计划绘制区域：新建围栏同步到人员定位系统
     */
    public Integer addEnclosure(String drawArea2, String billNumber, Long areaId) {
        // enclosureAdd + "?access_token="
        // /positionApi/api/enclosure/add?access_token
        Map<String, Object> map = new HashMap<>(10);
        map.put("name", "作业票围栏-" + billNumber);  // 作业名称
        map.put("areaId", areaId); // 地图ID
        map.put("threshold", 10);  // 消抖时间（秒
        map.put("overtime", 100);  // 超时时间（秒）
        map.put("entityTypes", JSONUtil.toJsonStr(Collections.singletonList("staff"))); // 围栏类型：car-车辆,staff-人员
        JSONArray jsonArray1 = JSONUtil.parseArray(drawArea2);

        List polygonPoint = jsonArray1.stream().map(item -> {
            JSONArray arry = JSONUtil.parseArray(item);
            return new PositionVo(arry.get(0).toString(), arry.get(1).toString());
        }).collect(Collectors.toList());
        map.put("polygonPoint", polygonPoint);
        map.put("shapeType", "polygon");
        map.put("enclosureType", 26);  // 围栏类型 22 内部车辆(car) 23 危险作业(dangerous) 24 内部人员(staff) 26 聚集类型
        log.info("人员定位系统-新增围栏，请求参数：{}", JSONUtil.toJsonStr(map));

        String result = GeoConfig.sendPost(GeoConfig.enclosureAdd, map);
        JSONObject jsonObj = JSONUtil.parseObj(result);
        if (!jsonObj.containsKey("data") || jsonObj.getInt("code") != 200) {
            return null;
        }
        JSONObject jsonObj2 = jsonObj.getJSONObject("data");
        if (jsonObj2==null || !jsonObj2.containsKey("id")) {
            return null;
        }
        return jsonObj2.getInt("id");
    }

    public List<EnclosureInfo> getEnclosureList() {
        List<EnclosureInfo> list = HandleEnclosure();

        if (StringUtils.isNotEmpty(list)) {
            for(EnclosureInfo enclosure : list) {
                if (enclosure.getId()==null) {
                    enclosureInfoService.insertEnclosureInfo(enclosure);
                }
            }
        }

        return list;
    }

    public List<EnclosureInfo> HandleEnclosure() {
        String jsonStr = getEnclosureList(null, null);
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        if (jsonObject.getInt("code")!=200) {
            return Collections.emptyList();
        }

        JSONObject jsonObject2 = jsonObject.getJSONObject("data");
        JSONArray jsonArray = jsonObject2.getJSONArray("records");

        if (jsonArray == null) {
            return Collections.emptyList();
        }

        // 遍历内层数组中的每个对象
        EnclosureInfo enclosure = null;
        List<EnclosureInfo> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size();  i++) {
            enclosure = new EnclosureInfo();
            JSONObject jsonObj = jsonArray.getJSONObject(i);
            Integer synId = jsonObj.getInt("id");
            EnclosureInfo entity = enclosureInfoService.selectEnclosureBySynId(synId);
            if (entity!=null) {
                enclosure.setId(entity.getId());
                enclosure.setGovernId(entity.getGovernId());
//                if (StringUtils.isEmpty(entity.getGovernId())) {
//                    entity.setZoneType("1");
//                    list.add(entity);
//                }
//                continue;
            }

            enclosure.setSynId(jsonObj.getInt("id"));
            enclosure.setName(jsonObj.getStr("name"));
            enclosure.setAreaIds(jsonObj.getStr("areaIds"));
            enclosure.setShape(jsonObj.getInt("shape"));
            enclosure.setEnclosureType(jsonObj.getInt("enclosureType"));
            JSONArray json = jsonObj.getJSONArray("loatCoordinates");
            enclosure.setCoordinates(json!=null ? json.toString() : null);
            enclosure.setEntityTypes("staff");
            enclosure.setState(jsonObj.getInt("status"));  // 状态(0:开启 1:关闭)
            enclosure.setDelFlag("0");
            enclosure.setCreatedBy("admin");
            enclosure.setZoneType("1"); // 区域类型：0临时区域, 1固定区域
            enclosure.setCreatedDate(new Date());
            list.add(enclosure);
        }

        return list;
    }


    /**
     * 查询地图下指定类型的围栏
     *
     * @return
     */
    public String getEnclosureList(Integer fenceId, String name) {
        Map<String, Object> map = new HashMap<>(10);
        map.put("orgId", 100);             // 厂区id
        map.put("fenceId", fenceId);       // 围栏id
        map.put("name", name);             // 围栏名称
        log.info("请求围栏数据，请求参数：{}", JSONUtil.toJsonStr(map));

        String result = GeoConfig.sendPost(GeoConfig.enclosureList, map);
        log.info("厂区id {} 围栏id {}, 围栏名称 {}, 返回围栏信息 {}", 100, fenceId, name, result);

        return result;
    }


    /**
     * 查找地图上的指定围栏
     * 通过 地图ID 和 围栏名称
     *
     * @param areaId
     * @param enclosureName
     * @return
     */
    public Integer getEenclosureId(String areaId, String enclosureName) {
        Map<String, Object> map = new HashMap<>(10);
        map.put("areaId", areaId);            // 地图id
        map.put("enclosureMode", "staff");    // 围栏模型: car-车辆报警 dangerous-危险源报警 staff-人员报警
        log.info("绘制区域-作业计划模块-发送获取围栏信息，请求参数：{}", JSONUtil.toJsonStr(map));

        String result = GeoConfig.sendPost(GeoConfig.enclosureList, map);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        JSONArray jsonArray = jsonObject.containsKey("data") ? jsonObject.getJSONArray("data") : null;
        if (jsonArray==null || jsonArray.isEmpty())  { return null;}
        JSONObject obj = jsonArray.stream().map(item -> (JSONObject)item).filter(item -> enclosureName.equals(item.get("name"))).findFirst().orElse(null);
        log.info("绘制区域-作业计划模块-发送获取围栏信息，返回结果：{}", jsonArray);
        return obj != null ? obj.getInt("id") : null;
    }

    /**
     * 删除围栏
     * @param enclosureId
     */
    public void delEnclosure(Integer enclosureId) {
        if (enclosureId==null)  { return ;}
        JSONObject jsonObject = GeoConfig.sendGet(GeoConfig.enclosureDel + enclosureId + "?access_token=" + PersonPosition.getToken());
        log.info("绘制区域-作业计划模块-删除围栏，返回结果：{}", jsonObject);
    }

    /**
     * 新增报警规则
     */
    public Integer addRule(String billNumber, Integer enclosureId, int maxCount) {
        // /positionApi/api/warnTrigger/add?access_token=
        Map<String, Object> map = new HashMap<>(10);
        map.put("name", "作业票-" + billNumber + "-超员报警规则");  // 名称
        map.put("enclosureId", enclosureId);  // 围栏id
        map.put("modeId", 2);                 // 模式id
        map.put("warnTarget", "staff");       // 围栏模型
        Map<String, Object> conditions = new HashMap<>(1);
        conditions.put("maxCount", maxCount);
        map.put("conditions", JSONUtil.toJsonStr(conditions)); // 围栏类型：car-车辆,staff-人员
        map.put("orgId", GeoConfig.orgId);      // 厂区id
        log.info("人员定位系统-新增报警规则, 请求参数：{}", JSONUtil.toJsonStr(map));

        String result = GeoConfig.sendPost(GeoConfig.warnTriggerAdd, map);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        if (!jsonObject.containsKey("data") || jsonObject.getInt("code") != 200) {
            return null;
        }
        JSONObject jsonObj2 = jsonObject.getJSONObject("data");
        if (jsonObj2==null || !jsonObj2.containsKey("id")) {
            return null;
        }
        return jsonObj2.getInt("id");
    }

    /**
     * 删除报警规则
     * @param warnRuleId
     */
    public void delRule(Integer warnRuleId) {
        if (warnRuleId==null)  { return ; }
        JSONObject jsonObject = GeoConfig.sendGet(GeoConfig.warnTriggerDel + warnRuleId + "?access_token=" + PersonPosition.getToken());
        log.info("绘制区域-作业计划模块-删除报警规则，返回结果：{}", jsonObject);
    }


    public String subscribeList() {
        JSONObject jsonObject = GeoConfig.sendGet(GeoConfig.subscribeList + "?access_token=" + PersonPosition.getToken());
        log.info("所有的订阅事件：{}", jsonObject);

        return jsonObject.toString();
    }



    class PositionVo implements Serializable {

        public PositionVo(String x, String y) {
            this.x = x;
            this.y = y;
        }

        private String x;
        private String y;

        public String getX() {
            return x;
        }

        public void setX(String x) {
            this.x = x;
        }

        public String getY() {
            return y;
        }

        public void setY(String y) {
            this.y = y;
        }
    }

}
